/*
 * Copyright (c) Huawei Device Co., Ltd. 2024. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef DER_PARSER_H
#define DER_PARSER_H

#include <string>
#include <vector>

namespace OHOS {
namespace SE {
// reference: asn.1 specification
const static uint8_t ASN1_OCTET_STRING = 0x04;
const static uint8_t ASN1_OID = 0x06;
const static uint8_t ASN1_SEQUENCE = 0x30;
const static uint8_t ASN1_APPL_IDENTIFIER = 0x4F;
const static uint8_t ASN1_APPL_LABEL = 0x50;
const static uint8_t ASN1_APPL_PATH = 0x51;
const static uint8_t ASN1_APPL_TEMPLATE = 0x61;
const static uint8_t ASN1_FCP = 0x62;
const static uint8_t ASN1_PADDING_BYTE = 0xFF;

class DerParser {
public:
    DerParser(const std::vector<uint8_t> &derData);
    ~DerParser();

    /**
     * @brief Get tlv type by current der index
     * @return current tlv type
     */
    uint8_t GetTlvType();

    /**
     * @brief Get tlv data length by current der index and tlv type
     * @param type tlv type to be parsed
     * @return current tlv data length
     */
    uint16_t GetTlvDataLength(uint8_t type);

    /**
     * @brief Get tlv data by current der index
     * @return current tlv data
     */
    std::vector<uint8_t> GetTlvData();

    /**
     * @brief Check is end of parsing current der data
     * @return Is end of parsing
     */
    bool IsParsingEnd();

    /**
     * @brief Skip current tlv data parsing
     */
    void SkipTlvData();

    /**
     * @brief Parse EF path field by current der index
     * @return EF path
     */
    std::vector<uint8_t> ParseEfPath();

    /**
     * @brief Parse OID by current der index (only needed by DODF)
     * @return DODF Oid
     */
    std::string ParseDodfOid();

    /**
     * @brief Get current der parsing index and tlv data length
     * @param currentIndex current der parsing index
     * @param tlvDataLength current tlv data length
     */
    void GetParsingStatus(uint8_t &currentIndex, uint8_t &tlvDataLength);

    /**
     * @brief Recover parsing status by index and tlv data length
     * @param currentIndex current der parsing index
     * @param tlvDataLength current tlv data length
     */
    void RecoverParsingStatus(uint8_t currentIndex, uint8_t tlvDataLength);

private:
    bool GetTlvTypeInner(uint8_t &tlvType);
    bool GetTlvSize(uint16_t &tlvSize);
    uint32_t ParseSubIdOfOid();

    std::vector<uint8_t> derData_;
    uint16_t derDataLength_ = 0;
    uint16_t derCurrentIndex_ = 0;
    uint16_t tlvDataLength_ = 0;
};
}  // namespace SE
}  // namespace OHOS
#endif // DER_PARSER_H